﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Fleck;

namespace PPTHelper
{

    class WsResutl : HttpResutl
    {
        public enum TypeEnum { Text, Binary };
        public TypeEnum MessageType { get; private set; }
        public WsResutl(string content) : base(content) { MessageType = TypeEnum.Text; }
        public WsResutl(byte[] Bytes) : base(Bytes) { MessageType = TypeEnum.Binary; }
    }

    class WsServer
    {
        public static int Port { get; set; }
        readonly WebSocketServer server;
        public List<IWebSocketConnection> WsClient { get; private set; }
        public Dictionary<string, Func<string, WsResutl>> RouteFunc { get; set; }

        public WsServer(int port = 8081)
        {
            Port = port;
            RouteFunc = new Dictionary<string, Func<string, WsResutl>>
            {
                { "/hi", (msg) =>  new WsResutl($"Hello world! Echo：{msg}") }
            };
            server = new WebSocketServer($"ws://0.0.0.0:{Port}");
            WsClient = new List<IWebSocketConnection>();
        }

        public void Start()
        {
            server.RestartAfterListenError = true;
            server.Start(
                socket =>
                {
                    socket.OnOpen = () =>
                    {
                        var ip = socket.ConnectionInfo.ClientIpAddress;
                        var path = socket.ConnectionInfo.Path;
                        Log.Info($"Open：{ip} path：{path}");
                        if (RouteFunc.ContainsKey(path)) WsClient.Add(socket); else socket.Close();
                    };

                    socket.OnMessage = (msg) =>
                    {
                        var path = socket.ConnectionInfo.Path;
                        Log.Info("Message：" + path);
                        if (RouteFunc.ContainsKey(path))
                        {
                            //回调
                            var result = RouteFunc[path]?.Invoke(msg);
                            if (result?.ByteArray?.Length > 0)
                            {
                                if (result.MessageType == WsResutl.TypeEnum.Binary)
                                {
                                    socket.Send(result.ByteArray);
                                }
                                else
                                {
                                    socket.Send(result.TextContent);
                                }
                            }
                        }
                    };

                    socket.OnClose = () =>
                        {
                            Log.Info("Close：" + socket.ConnectionInfo.ClientIpAddress);
                            WsClient.Remove(socket);
                        };
                });
        }

        public void Broadcast(string msg) => WsClient.ForEach(ws => ws.Send(msg));

        public void Broadcast(byte[] bytes) => WsClient.ForEach(ws => ws.Send(bytes));

        public void Stop() => server.Dispose();

    }
}
